home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / os2 / cppdoc.zip / cppdoc.cmd next >
OS/2 REXX Batch file  |  1996-09-07  |  44KB  |  1,192 lines

  1. /* --------------------------------------------------------------------------
  2.  * $RCSfile: cppdoc.cmd,v $
  3.  * $Revision: 1.10 $
  4.  * $Date: 1996/09/07 16:26:57 $
  5.  * $Author: Bablok $
  6.  * --------------------------------------------------------------------------
  7.  * Synopsis:
  8.  *
  9.  * Documentation-Generator for C++ programs.
  10.  *
  11.  * cppdoc.cmd and cppdoc.htm are Copyright (c) 1996 by Bernhard Bablok
  12.  * --------------------------------------------------------------------------
  13.  * History:
  14.  *
  15.  * $Log: cppdoc.cmd,v $
  16.  * Revision 1.10  1996/09/07 16:26:57  Bablok
  17.  * Various new features
  18.  * New commandline interface
  19.  *
  20.  * Revision 1.0  1996/06/06 14:25:36  Bablok
  21.  * Initial revision
  22.  *
  23.  * -------------------------------------------------------------------------- */
  24.  
  25. PARSE ARG cmdLine
  26.  
  27. CALL initConstants
  28. CALL processArgs
  29. CALL readIndex
  30. DO numCycles
  31.    DO fileNr = GetOpt._optind TO GetOpt.0
  32.       CALL initVars GetOpt.fileNr
  33.       CALL readFiles
  34.       CALL findClasses
  35.       CALL findMember
  36.       CALL printDoc
  37.    END
  38. END
  39. CALL updateIndexFile
  40. RETURN 0
  41.  
  42. /* -------------------------------------------------------------------------- */
  43. /* some utility functions, for performance reasons at the head of the file    */
  44. /* -------------------------------------------------------------------------- */
  45.  
  46. /* -------------------------------------------------------------------------- */
  47. /* nextIdentifier: return position of next identifier and identifier          */
  48. /*                 of a given string                                          */
  49. /* -------------------------------------------------------------------------- */
  50. nextIdentifier: PROCEDURE
  51.  
  52. PARSE ARG string, start
  53.  
  54. IF string = '' THEN
  55.   RETURN 0 ''
  56. IF start = '' THEN
  57.   start = 1
  58. IF start > LENGTH(string) THEN
  59.   RETURN 0 ''
  60.  
  61. string = SUBSTR(string,start)
  62. first = VERIFY(string,'_abcdefghijklmnopqrstuvwxyz' ||,
  63.                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789','M')
  64. IF first = 0 THEN
  65.   RETURN 0 ''
  66.  
  67. string = SUBSTR(string,first)
  68. len = VERIFY(string,'_abcdefghijklmnopqrstuvwxyz' ||,
  69.                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') - 1
  70. IF len = -1 THEN
  71.   len = LENGTH(string)
  72. ident = SUBSTR(string,1,len)
  73. IF ident = 'operator' & POS('(',string,len+1) > 2 THEN
  74.   ident = SPACE(SUBSTR(string,1,POS('(',string,len+1)-1),0)
  75.  
  76. RETURN start+first-1 ident
  77.  
  78. /* -------------------------------------------------------------------------- */
  79. /* lastIdentifier: return last (c++)-identifier in a given string             */
  80. /*                  (including ~ for destructor, expecting no bitwise NOT)    */
  81. /* -------------------------------------------------------------------------- */
  82. lastIdentifier: PROCEDURE
  83.  
  84. PARSE ARG string, start
  85.  
  86. IF string = '' THEN
  87.   RETURN ''
  88. IF start = '' THEN
  89.   start = LENGTH(string)
  90.  
  91. revString = REVERSE(STRIP(SUBSTR(string,1,start)))
  92. first = VERIFY(revString,'~_abcdefghijklmnopqrstuvwxyz' ||,
  93.                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789','M')
  94. IF first = 0 THEN
  95.   RETURN ''
  96. len = VERIFY(SUBSTR(revString,first),'~_abcdefghijklmnopqrstuvwxyz' ||,
  97.                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') - 1
  98. IF len = -1 THEN
  99.   len = LENGTH(revString) - (first-1)
  100. ident = REVERSE(SUBSTR(revString,first,len))
  101. IF ident = 'operator' THEN DO
  102.   ident = STRIP(REVERSE(STRIP(SUBSTR(revString,1,len+first-1),'L','(')))
  103. END                                          /* IF ident = 'operator' THEN DO */
  104. RETURN ident
  105.  
  106. /* -------------------------------------------------------------------------- */
  107. /* findMatchingChar: find position of closing parenthesis, brace etc          */
  108. /* -------------------------------------------------------------------------- */
  109. findMatchingChar: PROCEDURE
  110.  
  111. PARSE ARG string, start
  112.  
  113. cOpen = SUBSTR(string,start,1)
  114. SELECT
  115.   WHEN cOpen = '(' THEN cClose = ')'
  116.   WHEN cOpen = '{' THEN cClose = '}'
  117.   WHEN cOpen = '[' THEN cClose = ']'
  118.   WHEN cOpen = '<' THEN cClose = '>'
  119.   WHEN cOpen = ')' THEN cClose = '('
  120.   WHEN cOpen = '}' THEN cClose = '{'
  121.   WHEN cOpen = ']' THEN cClose = '['
  122.   WHEN cOpen = '>' THEN cClose = '<'
  123.   OTHERWISE
  124.     RETURN 0
  125. END                                                                 /* SELECT */
  126. IF POS(cOpen,')}]>') > 0 THEN DO
  127.   string = REVERSE(string)
  128.   start  = LENGTH(string) - start + 1
  129. END                                       /* IF POS(cOpen,')}]>') > 0 THEN DO */
  130.  
  131. open = 1
  132. next = 0
  133. DO FOREVER
  134.   charPos = VERIFY(SUBSTR(string,start+next+1),cOpen||cClose,'M')
  135.   IF charPos = 0 THEN                           /* actually, this is an error */
  136.     RETURN 0
  137.   next = next + charPos
  138.   char = SUBSTR(string,start+next,1)
  139.   IF char = cOpen THEN
  140.     open = open + 1
  141.   ELSE
  142.     open = open - 1
  143.   IF open = 0 THEN DO
  144.     matchingPos = start + next
  145.     IF POS(cOpen,')}]>') > 0 THEN
  146.       matchingPos = LENGTH(string) - matchingPos + 1
  147.     RETURN matchingPos
  148.   END                                                  /* IF open = 0 THEN DO */
  149. END                                                             /* DO FOREVER */
  150.  
  151. /* -------------------------------------------------------------------------- */
  152. /* makeExternalRef: add anchor tag for external reference                     */
  153. /* -------------------------------------------------------------------------- */
  154. makeExternalRef: PROCEDURE EXPOSE externalRefs. className
  155.  
  156. PARSE ARG line
  157.  
  158. start = 1
  159. CALL nextIdentifier line, start
  160. PARSE VALUE RESULT WITH identPos ident
  161. DO WHILE ident <> ''
  162.   IF externalRefs.ident <> '' & ident <> className THEN DO
  163.     ref  = '<A HREF="'externalRefs.ident'">'ident'</A>'
  164.     head = SUBSTR(line,1,identPos-1)
  165.     tail = SUBSTR(line,identPos+LENGTH(ident))
  166.     line = head || ref || tail
  167.     identPos = identPos + LENGTH(externalRefs.ident) + 15
  168.   END             /* IF externalRefs.ident <> '' & ident <> className THEN DO */
  169.   start = identPos + LENGTH(ident)
  170.   CALL nextIdentifier line, start
  171.   PARSE VALUE RESULT WITH identPos ident
  172. END                                                   /* DO WHILE ident <> '' */
  173. RETURN line
  174.  
  175. /* -------------------------------------------------------------------------- */
  176. /* makeInternalRef: add anchor tag for internal reference                     */
  177. /* -------------------------------------------------------------------------- */
  178. makeInternalRef: PROCEDURE
  179.  
  180. PARSE ARG string, refToken, refAnchor
  181.  
  182. ref = '<A HREF="#'refAnchor'">'refToken'</A>'
  183. PARSE VALUE string WITH head (refToken) tail
  184. RETURN head || ref || tail
  185.  
  186. /* -------------------------------------------------------------------------- */
  187. /* lastWord: return last word of given string                                 */
  188. /* -------------------------------------------------------------------------- */
  189. lastWord: PROCEDURE
  190.  
  191. PARSE ARG string
  192. RETURN WORD(string,WORDS(string))
  193.  
  194. /* -------------------------------------------------------------------------- */
  195. /* count: Return count of a given character in a given string                 */
  196. /* -------------------------------------------------------------------------- */
  197. count: PROCEDURE
  198.  
  199. PARSE ARG c, string
  200.  
  201. start = 1
  202. num   = 0
  203. DO FOREVER
  204.   col = POS(c,string,start)
  205.   IF col > 0 THEN DO
  206.     num   = num + 1
  207.     start = col + 1
  208.   END                                                   /* IF col > 0 THEN DO */
  209.   ELSE
  210.     RETURN num
  211. END                                                             /* DO FOREVER */
  212.  
  213. /* -------------------------------------------------------------------------- */
  214. /* changestr: Change multiple occurences of a given string                    */
  215. /* -------------------------------------------------------------------------- */
  216. changestr: PROCEDURE
  217.  
  218. PARSE ARG string, tableo, tablei, start, delim, once
  219.  
  220. IF start = '' THEN
  221.   start = 1
  222. IF delim = '' THEN
  223.   delim = ' '
  224. IF once = '' THEN
  225.   once = 0
  226.  
  227. DO FOREVER
  228.   IF tablei = '' THEN
  229.     LEAVE
  230.   PARSE VALUE tablei WITH oldToken (delim) tablei
  231.   PARSE VALUE tableo WITH newToken (delim) tableo
  232.   DO FOREVER
  233.     IF POS(oldToken,string,start) = 0 THEN
  234.       LEAVE
  235.     PARSE VALUE SUBSTR(string,start) WITH head (oldToken) rest
  236.     IF start > 1 THEN
  237.       string = SUBSTR(string,1,start-1) || head || newToken || rest
  238.     ELSE
  239.       string = head || newToken || rest
  240.     IF once THEN
  241.       LEAVE
  242.   END                                                           /* DO FOREVER */
  243. END                                                             /* DO FOREVER */
  244. RETURN string
  245.  
  246. /* -------------------------------------------------------------------------- */
  247. /* initConstants: Define constants                                            */
  248. /* -------------------------------------------------------------------------- */
  249. initConstants:
  250.  
  251. MSG_READ_FILES        = "Reading files ..."
  252. MSG_READ_INDEX        = "Reading index"
  253. MSG_FIND_CLASSES      = "Looking for class declarations"
  254. MSG_FIND_MEMBER       = "Looking for member definitions"
  255. MSG_PRINT_DOC         = "Generating documentation..."
  256. MSG_PRINT_DESC        = "... class description"
  257. MSG_PRINT_INHER       = "... class inheritance"
  258. MSG_CLASS_INTERFACE   = "... class interface"
  259. MSG_MEMBER_DOC        = "... member description"
  260. ERR_TARGET_DIR        = "Error: Target directory does not exist"
  261. ERR_FILE_NOT_FOUND    = "Error: File" fileName "not found"
  262. ERR_NO_FILES          = "Error: No files"
  263. ERR_INVALID_INDEX     = "Error: Index-file" indexFile "is invalid"
  264. ERR_UNBALANCED_BRACES = "Error: Missing '}'"
  265.  
  266. DOC_TITLE       = 'Class Documentation for C++-Class: '
  267. SOURCE_H2       = 'Source'
  268. CLASS_INH_H2    = 'Inheritance'
  269. CLASS_DOC_H2    = 'Class Description'
  270. CLASS_DOC_NONE  = 'No description available.'
  271. CLASS_INT_H2    = 'Class Interface'
  272. CLASS_INT_REF   = 'Return to class interface.'
  273. CLASS_INT_NONE  = 'Class declaration not found.'
  274. MEMBER_DOC_H2   = 'Description of Functions (Members and Others)'
  275. MEMBER_DOC_NONE = 'No details about members available.'
  276. INDEX_TITLE     = 'Index to C++-Class Documentation'
  277. INDEX_H1        = 'Index'
  278.  
  279.  
  280. CPP_EXTENSIONS  = 'cpp cc cxx c'
  281. NLS_CHAR_ESC    = 'ä ö ü Ä Ö Ü ß'
  282. NLS_CHAR        = 'ä ö ü Ä Ö Ü ß'
  283. MAX_LINE_LENGTH = 70
  284.  
  285. CALL RxFuncAdd 'SysFileDelete', 'RexxUtil', 'SysFileDelete'
  286. CALL RxFuncAdd 'SysFileTree', 'RexxUtil', 'SysFileTree'
  287. RETURN
  288.  
  289. /* -------------------------------------------------------------------------- */
  290. /* processArgs: process command line arguments, setup variables               */
  291. /* -------------------------------------------------------------------------- */
  292. processArgs:
  293.  
  294. CALL setupArg cmdLine
  295. GetOpt._opterr = 0
  296.  
  297. printAll            = 1
  298. printSource         = 0
  299. printDesc           = 0
  300. printInter          = 0
  301. printMem            = 0
  302. omitTrailer         = 0
  303. numCycles           = 1
  304. relativeLinks       = 0
  305. targetDirectory     = '.'
  306. indexFile           = ''
  307. hidePrivateSections = 0
  308. optstr              = 'x:t:r2Hsdimo'
  309.  
  310. DO UNTIL c = -1 | c = '?'
  311.   c = GetOpt(optstr)
  312.   SELECT
  313.     WHEN c = 'x' THEN
  314.       indexFile = GetOpt._optarg
  315.     WHEN c = 't' THEN
  316.       targetDirectory = STRIP(GetOpt._optarg,'T','\')
  317.     WHEN c = 'r' THEN
  318.       relativeLinks = 1
  319.     WHEN c = '2' THEN
  320.       numCycles = 2
  321.     WHEN c = 'H' THEN
  322.       hidePrivateSections = 1
  323.     WHEN c = 's' THEN DO
  324.       printAll    = 0
  325.       printSource = 1
  326.     END
  327.     WHEN c = 'd' THEN DO
  328.       printAll    = 0
  329.       printDesc   = 1
  330.     END
  331.     WHEN c = 'i' THEN DO
  332.       printAll    = 0
  333.       printInter  = 1
  334.     END
  335.     WHEN c = 'm' THEN DO
  336.       printAll    = 0
  337.       printMem    = 1
  338.     END
  339.     WHEN c = 'o' THEN
  340.       omitTrailer = 1
  341.     WHEN c = '?' THEN
  342.       CALL usage
  343.     OTHERWISE
  344.       NOP
  345.   END
  346. END
  347. IF printAll THEN DO
  348.   printSource = 1
  349.   printDesc   = 1
  350.   printInter  = 1
  351.   printMem    = 1
  352. END
  353.  
  354. curDir = DIRECTORY()
  355. targetDirectory = DIRECTORY(targetDirectory)
  356. CALL DIRECTORY curDir
  357. IF targetDirectory = '' THEN DO
  358.   SAY ERR_TARGET_DIR
  359.   EXIT 3
  360. END
  361. ELSE
  362.   targetDirectory = targetDirectory'\'
  363. IF indexFile <> '' THEN
  364.   indexFile = targetDirectory || indexFile
  365.  
  366. /* process filename arguments   --------------------------------------------- */
  367.  
  368. i = GetOpt._optind
  369. DO WHILE i <= GetOpt.0
  370.    IF POS('*',GetOpt.i) > 0 | POS('?',GetOpt.i) > 0 THEN DO
  371.       CALL SysFileTree GetOpt.i,'files.','FO'
  372.       DO j = i+1 TO GetOpt.0
  373.          k = j - 1
  374.          GetOpt.k = GetOpt.j
  375.       END
  376.       DO j = 1 TO files.0
  377.          k = GetOpt.0 - 1 + j
  378.          GetOpt.k = files.j
  379.       END
  380.       GetOpt.0 = GetOpt.0 + files.0 - 1
  381.    END
  382.    ELSE
  383.       i = i + 1
  384. END
  385. IF GetOpt._optind > GetOpt.0 THEN DO
  386.   SAY ERR_NO_FILES
  387.   CALL usage
  388. END
  389.  
  390. RETURN
  391.  
  392. /* -------------------------------------------------------------------------- */
  393. /* initVars: Initialize Variables                                             */
  394. /* -------------------------------------------------------------------------- */
  395. initVars:
  396.  
  397. PARSE ARG fileName
  398. fileName = STREAM(fileName,'C','query exists')
  399. IF fileName = '' THEN DO
  400.   SAY ERR_FILE_NOT_FOUND
  401.   EXIT 3
  402. END                                               /* IF fileName = '' THEN DO */
  403. sourceFiles = '<A HREF="file:///'fileName'">'fileName'</A>'
  404.  
  405. classList       = ''
  406. classDocu.      = ''
  407. classInterf.    = ''
  408. classInherit.   = ''
  409. classBase.      = ''
  410. classMember.    = ''
  411. memberDef.      = ''
  412. memberDocu.     = ''
  413.  
  414. RETURN 0
  415.  
  416. /* -------------------------------------------------------------------------- */
  417. /* readFiles: Read interface and implementation files                         */
  418. /* -------------------------------------------------------------------------- */
  419. readFiles:
  420.  
  421. SAY MSG_READ_FILES
  422.  
  423. i = 0
  424. SAY '...' fileName
  425. DO WHILE LINES(fileName) > 0
  426.   i = i + 1
  427.   line.i = STRIP(LINEIN(fileName),'T')
  428.   IF line.i = '' THEN DO
  429.     i = i - 1
  430.     ITERATE
  431.   END                                               /* IF line.i = '' THEN DO */
  432.   ELSE IF WORD(line.i,1) = '#define' THEN DO
  433.     DO UNTIL RIGHT(line.i,1) <> '\'
  434.       line.i = STRIP(LINEIN(fileName),'T')
  435.     END                                    /* DO UNTIL RIGHT(line.i,1) <> '\' */
  436.     i = i - 1
  437.     ITERATE
  438.   END
  439.   ELSE IF LEFT(STRIP(line.i),4) = '//@p' THEN DO
  440.     IF hidePrivateSections THEN DO
  441.       i = i - 1
  442.       ITERATE
  443.     END
  444.     ELSE DO
  445.       ppos = POS('//@p',line.i) + 3
  446.       line.i = OVERLAY(' ',line.i,ppos)
  447.     END
  448.   END
  449. END                                           /* DO WHILE LINES(fileName) > 0 */
  450. CALL LINEOUT fileName
  451.  
  452. DO j = 1 TO WORDS(CPP_EXTENSIONS)
  453.   impFile = SUBSTR(fileName,1,LASTPOS('.',fileName)) || WORD(CPP_EXTENSIONS,j)
  454.   impFile = STREAM(impFile,'C','query exists')
  455.   IF impFile <> '' THEN DO
  456.     SAY '...' impFile
  457.     sourceFiles = sourceFiles',' '<A HREF="file:///'impFile'">'impFile'</A>'
  458.     DO WHILE LINES(impFile) > 0
  459.       i = i + 1
  460.       line.i = STRIP(LINEIN(impFile))
  461.       IF line.i = '' THEN DO
  462.         i = i - 1
  463.         ITERATE
  464.       END                                           /* IF line.i = '' THEN DO */
  465.       ELSE IF WORD(line.i,1) = '#define' THEN DO
  466.         DO UNTIL RIGHT(line.i,1) <> '\'
  467.           line.i = STRIP(LINEIN(impFile),'T')
  468.         END                                /* DO UNTIL RIGHT(line.i,1) <> '\' */
  469.         i = i - 1
  470.         ITERATE
  471.       END                                /* DO UNTIL RIGHT(line.i,1) <> '\' */
  472.       ELSE IF LEFT(line.i,4) = '//@p' THEN DO
  473.         IF hidePrivateSections THEN DO
  474.           i = i - 1
  475.           ITERATE
  476.         END
  477.         ELSE DO
  478.           ppos = POS('//@p',line.i) + 3
  479.           line.i = OVERLAY(' ',line.i,ppos)
  480.         END
  481.       END
  482.     END                                        /* DO WHILE LINES(impFile) > 0 */
  483.     CALL LINEOUT impFile
  484.     LEAVE
  485.   END                                             /* IF impFile <> '' THEN DO */
  486. END                                      /* DO j = 1 TO WORDS(CPP_EXTENSIONS) */
  487. line.0 = i
  488. lastLine = line.0   /* default value, in case file does not contain class def */
  489. RETURN
  490.  
  491. /* -------------------------------------------------------------------------- */
  492. /* readIndex: Read index file                                                 */
  493. /* -------------------------------------------------------------------------- */
  494. readIndex:
  495.  
  496. indexAddBefore = 0
  497. externalRefsClassList = ''
  498. externalRefs.         = ''
  499. classIndexInfo.       = ''
  500.  
  501. IF indexFile <> '' THEN DO
  502.   IF POS('.',indexFile,LASTPOS('\',indexFile)+1) = 0 THEN
  503.     indexFile = STRIP(indexFile)'.htm'
  504.   IF STREAM(indexFile,'C','query exists') <> '' THEN DO
  505.     i = 0
  506.     SAY MSG_READ_INDEX indexFile
  507.     DO WHILE LINES(indexFile)
  508.       i = i + 1
  509.       index.i = LINEIN(indexFile)
  510.       index.i._class = '---'
  511.       IF LEFT(STRIP(index.i),4) = '<LI>' THEN DO
  512.         PARSE VALUE index.i WITH . '"' classNameFile '">' className '<' .
  513.         index.i._class = className
  514.         externalRefs.className = classNameFile
  515.       END                       /* IF LEFT(STRIP(index.i),4) = '<LI>' THEN DO */
  516.       ELSE IF LEFT(STRIP(index.i),5) = '</UL>' THEN
  517.         indexAddBefore = i
  518.     END                                          /* DO WHILE LINES(indexFile) */
  519.     CALL LINEOUT indexFile
  520.     index.0 = i
  521.     IF indexAddBefore = 0 THEN DO
  522.       SAY ERR_INVALID_INDEX
  523.       EXIT 3
  524.     END                                      /* IF indexAddBefore = 0 THEN DO */
  525.   END                /* IF STREAM(indexFile,'C','query exists') <> '' THEN DO */
  526. END                                             /* IF indexFile <> '' THEN DO */
  527. RETURN
  528.  
  529. /* -------------------------------------------------------------------------- */
  530. /* findClasses: find class declarations                                       */
  531. /* -------------------------------------------------------------------------- */
  532. findClasses:
  533.  
  534. SAY MSG_FIND_CLASSES
  535.  
  536. comment = 0
  537. DO i = 1 TO line.0
  538.  
  539.   /* skip comment lines   --------------------------------------------------- */
  540.  
  541.   IF LEFT(STRIP(line.i),2) = '//' THEN
  542.     ITERATE
  543.   ELSE IF comment & POS('*/',line.i) = 0 THEN
  544.     ITERATE
  545.   ELSE IF comment THEN DO
  546.     comment = 0
  547.     ITERATE
  548.   END                                              /* ELSE IF comment THEN DO */
  549.   ELSE IF POS('/*',line.i) > 0 & POS('*/',line.i) = 0 THEN DO
  550.     comment = 1
  551.     ITERATE
  552.   END          /* ELSE IF POS('/*',line.i) > 0 & POS('*/',line.i) = 0 THEN DO */
  553.   ELSE IF POS('/*',line.i) > 0 THEN
  554.     ITERATE
  555.  
  556.   /* check if class token is present   -------------------------------------- */
  557.  
  558.   IF POS('class',line.i) > 0 THEN DO
  559.  
  560.     /* concatenate lines until end of statement or beginning of declaration */
  561.  
  562.     line = line.i
  563.     n = i - 1
  564.     DO WHILE i < line.0 & POS(';',line) = 0 & POS('{',line) = 0
  565.       i = i + 1
  566.       line = line line.i
  567.     END        /* DO WHILE i < line.0 & POS(';',line) = 0 & POS('{',line) = 0 */
  568.  
  569.     /* omit template definitions of functions   ----------------------------- */
  570.  
  571.     IF WORDPOS('template',line) > 0 THEN DO
  572.       lt = POS('<',line)
  573.       IF WORDPOS('class',SUBSTR(line,findMatchingChar(line,lt))) = 0 THEN
  574.         ITERATE
  575.     END                            /* IF WORDPOS('template',line) > 0 THEN DO */
  576.  
  577.     /* omit forward declarations   ------------------------------------------ */
  578.  
  579.     IF POS('{',line) > 0 THEN DO                 /* found a class declaration */
  580.       IF POS(':',line) = 0 THEN DO               /* no classes inherited from */
  581.         PARSE VALUE line WITH this '{' .
  582.         className = lastWord(this)
  583.         classInherit.className = this
  584.       END                                     /* IF POS(':',line) = 0 THEN DO */
  585.       ELSE DO
  586.         PARSE VALUE line WITH this ':' base '{' .
  587.         className = lastWord(this)
  588.         classInherit.className = this ':' base
  589.       END                                                          /* ELSE DO */
  590.       classList = classList className
  591.       IF WORDPOS(className,externalRefsClassList) = 0 THEN
  592.         externalRefsClassList = externalRefsClassList className
  593.       IF relativeLinks THEN
  594.         externalRefs.className = className'.htm'
  595.       ELSE
  596.         externalRefs.className = 'file:///'targetDirectory||className'.htm'
  597.       CALL findClassDocu className, n
  598.       CALL findClassInterface className, line
  599.     END                                       /* IF POS('{',line) > 0 THEN DO */
  600.   END                                   /* IF POS('class',line.i) > 0 THEN DO */
  601. END                                                     /* DO i = 1 TO line.0 */
  602. RETURN
  603.  
  604. /* -------------------------------------------------------------------------- */
  605. /* findClassDocu: extract class documentation                                 */
  606. /* -------------------------------------------------------------------------- */
  607. findClassDocu: PROCEDURE EXPOSE line. classDocu. classIndexInfo.
  608.  
  609. PARSE ARG className, n
  610.  
  611. DO i = n TO 1 BY -1 UNTIL LEFT(STRIP(line.i),3) = '//@'
  612. END                /* DO i = n TO 1 BY -1 UNTIL LEFT(STRIP(line.i),3) = '//@' */
  613. IF i > 0 THEN DO
  614.   j = 0
  615.   DO WHILE i > 0 & LEFT(STRIP(line.i),3) = '//@'
  616.     j = j + 1
  617.     classDocu.className.j = STRIP(SUBSTR(STRIP(line.i),4))
  618.     i = i - 1
  619.   END                       /* DO WHILE i > 0 & LEFT(STRIP(line.i),3) = '//@' */
  620.   classIndexInfo.className = classDocu.className.j
  621.   classDocu.className.0 = j - 1
  622. END                                                       /* IF i > 0 THEN DO */
  623. ELSE
  624.   classDocu.className.0 = 0
  625. RETURN
  626.  
  627. /* -------------------------------------------------------------------------- */
  628. /* findClassInterface: extract class interface                                */
  629. /* -------------------------------------------------------------------------- */
  630. findClassInterface: PROCEDURE EXPOSE line. classInterf. i lastLine
  631.  
  632. PARSE ARG className, line
  633.  
  634. line.i = STRIP(SUBSTR(line' ',POS('{',line)+1))
  635. IF line.i = '' THEN
  636.   i = i + 1
  637. open = 1
  638. j = 0
  639. DO i = i TO line.0
  640.   open = open + count('{',line.i) - count('}',line.i)
  641.   IF open < 0  THEN DO
  642.     SAY ERR_UNBALANCED_BRACES
  643.     EXIT 3
  644.   END                                                 /* IF open < 0  THEN DO */
  645.   ELSE IF open = 0 THEN DO
  646.     endPos = LASTPOS('}',line.i)                  /* ELSE IF open = 0 THEN DO */
  647.     line = STRIP(SUBSTR(line.i,1,endPos-1))
  648.     IF line <> '' THEN DO
  649.       j = j + 1
  650.       classInterf.className.j = line
  651.     END                                              /* IF line <> '' THEN DO */
  652.     LEAVE i
  653.   END                                             /* ELSE IF open = 0 THEN DO */
  654.   ELSE DO
  655.     j = j + 1
  656.     classInterf.className.j = line.i
  657.   END                                                              /* ELSE DO */
  658. END                                                     /* DO i = i TO line.0 */
  659. lastLine = i
  660. classInterf.className.0 = j
  661. RETURN
  662.  
  663. /* -------------------------------------------------------------------------- */
  664. /* findMember: locate member definition                                       */
  665. /* -------------------------------------------------------------------------- */
  666. findMember:
  667.  
  668. SAY MSG_FIND_MEMBER
  669.  
  670. DO i = lastLine + 1 TO line.0
  671.  
  672.   /* skip lines before next docu-block   ------------------------------------ */
  673.  
  674.   DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) <> '//@'
  675.     i = i + 1
  676.     ITERATE
  677.   END                /* DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) <> '//@' */
  678.  
  679.   /* read docu-block   ------------------------------------------------------ */
  680.  
  681.   IF i <= line.0 & LEFT(STRIP(line.i),3) = '//@'  THEN DO
  682.     j = 0
  683.     DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) = '//@'
  684.       j = j + 1
  685.       doc.j = STRIP(SUBSTR(STRIP(line.i),4))
  686.       i = i + 1
  687.     END               /* DO WHILE i <= line.0 & LEFT(STRIP(line.i),3) = '//@' */
  688.     doc.0 = j
  689.   END              /* IF i <= line.0 & LEFT(STRIP(line.i),3) = '//@'  THEN DO */
  690.  
  691.   /* read member definition   ----------------------------------------------- */
  692.  
  693.   IF i <= line.0 THEN DO
  694.     line = STRIP(line.i)
  695.     line = changestr(line,'°°','::')
  696.     DO WHILE i <= line.0 & POS('{',line) = 0 & POS(':',line) = 0
  697.       i = i + 1
  698.       line = line STRIP(line.i)
  699.       line = changestr(line,'°°','::')
  700.     END       /* DO WHILE i <= line.0 & POS('{',line) = 0 & POS(':',line) = 0 */
  701.     IF POS(':',line) > 0 THEN
  702.       line = STRIP(SUBSTR(line,1,POS(':',line)-1))  /* this is a constructor! */
  703.     ELSE
  704.       line = STRIP(SUBSTR(line,1,POS('{',line)-1))
  705.     line = changestr(line,'::','°°')
  706.  
  707.     /* try to find a function/member definition   --------------------------- */
  708.  
  709.     start = findMatchingChar(line,LASTPOS(')',line))-1
  710.     memberName = SPACE(lastIdentifier(line,start),0)
  711.     start = start - LENGTH(memberName) -,
  712.                       POS(REVERSE(memberName),REVERSE(SUBSTR(line,1,start))) + 1
  713.     IF RIGHT(STRIP(SUBSTR(line,1,start)),2) = '::' THEN DO       /* a member! */
  714.       col = LASTPOS('::',line,start)
  715.       DO WHILE col > 0
  716.         IF RIGHT(STRIP(SUBSTR(line,1,col-1)),1) = '>' THEN      /* a template */
  717.           col = findMatchingChar(line,LASTPOS('>',line,col-1))
  718.         ident = lastIdentifier(line,col-1)
  719.         IF WORDPOS(ident,classList) > 0 THEN DO
  720.           className = ident
  721.           LEAVE
  722.         END                        /* IF WORDPOS(ident,classList) > 0 THEN DO */
  723.         ELSE
  724.           col = LASTPOS('::',line,col-1)
  725.       END                                                 /* DO WHILE col > 0 */
  726.     END             /* IF RIGHT(STRIP(SUBSTR(line,1,start)),2) = '::' THEN DO */
  727.  
  728.     memberName = changestr(memberName,'°amp; < >','& < >')
  729.     memberName = changestr(memberName,'&','°')
  730.     IF WORDPOS(memberName,classMember.className) > 0 THEN
  731.       memberName = memberName'!'i                              /* overloaded! */
  732.     classMember.className = classMember.className memberName
  733.     DO j=1 TO doc.0
  734.       memberDocu.className.memberName.j = doc.j
  735.     END                                                    /* DO j=1 TO doc.0 */
  736.     memberDocu.className.memberName.0 = doc.0
  737.     memberDef.className.memberName = line
  738.  
  739.   END                                               /* IF i <= line.0 THEN DO */
  740. END                                          /* DO i = lastLine + 1 TO line.0 */
  741. RETURN
  742.  
  743. /* -------------------------------------------------------------------------- */
  744. /* printDoc: generate HTML-file                                               */
  745. /* -------------------------------------------------------------------------- */
  746. printDoc:
  747.  
  748. DO i = 1 TO WORDS(classList)
  749.   className = WORD(classList,i)
  750.   docFile   = targetDirectory||className'.htm'
  751.   SAY MSG_PRINT_DOC className '...'
  752.   CALL SysFileDelete docFile
  753.   CALL printHeader
  754.   IF printSource THEN
  755.     CALL LINEOUT docFile, '<H2>'SOURCE_H2'</H2><P>'sourceFiles'<P><HR>'
  756.   IF printDesc THEN
  757.     CALL printClassDoc
  758.   IF printInter THEN DO
  759.     CALL printClassInheritance
  760.     CALL printClassInterface
  761.   END
  762.   IF printMem THEN
  763.     CALL printMemberDoc
  764.   CALL printTrailer docFile
  765.   CALL LINEOUT docFile
  766. END                                           /* DO i = 1 TO WORDS(classList) */
  767. RETURN
  768.  
  769. /* -------------------------------------------------------------------------- */
  770. /* printHeader: header for HTML-file, including source and inheritance        */
  771. /* -------------------------------------------------------------------------- */
  772. printHeader:
  773.  
  774. CALL LINEOUT docFile, '<!-- Class documentation generated by CPPDOC -->'
  775. CALL LINEOUT docFile, '<HTML>'
  776. CALL LINEOUT docFile, '<HEAD>'
  777. CALL LINEOUT docFile, '<TITLE>'DOC_TITLE className'</TITLE>'
  778. CALL LINEOUT docFile, '</HEAD>'
  779. CALL LINEOUT docFile, '<BODY>'
  780. CALL LINEOUT docFile, '<H1>Class' className'</H1>'
  781. RETURN
  782.  
  783. /* -------------------------------------------------------------------------- */
  784. /* printClassInheritance: Class inheritance                                   */
  785. /* -------------------------------------------------------------------------- */
  786. printClassInheritance:
  787.  
  788. SAY MSG_PRINT_INHER
  789.  
  790. CALL LINEOUT docFile, '<H2>'CLASS_INH_H2'</H2>'
  791.  
  792. indent = 0
  793. CALL LINEOUT docFile, '<P><PRE>'
  794. def = classInherit.className
  795. DO WHILE LENGTH(def) > MAX_LINE_LENGTH
  796.   splitPos = LASTPOS(',',def,MAX_LINE_LENGTH)
  797.   IF splitPos = 0 THEN
  798.     splitPos = LASTPOS(' ',def,MAX_LINE_LENGTH)
  799.   token = changestr(SUBSTR(def,1,splitPos),'°amp; < >','& < >')
  800.   token = changestr(token,'&','°')
  801.   def   = STRIP(SUBSTR(def,splitPos+1))
  802.   CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(token)
  803.   indent = 5
  804. END                                 /* DO WHILE LENGTH(def) > MAX_LINE_LENGTH */
  805. def = changestr(def,'°amp; < >','& < >')
  806. def = changestr(def,'&','°')
  807. CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(def)
  808. CALL LINEOUT docFile, '</PRE></P>'
  809.  
  810.  
  811. CALL LINEOUT docFile, '<HR>'
  812. RETURN
  813.  
  814. /* -------------------------------------------------------------------------- */
  815. /* printClassDoc: class description                                           */
  816. /* -------------------------------------------------------------------------- */
  817. printClassDoc:
  818.  
  819. SAY MSG_PRINT_DESC
  820.  
  821. CALL LINEOUT docFile, '<H2>'CLASS_DOC_H2'</H2><P>'
  822. IF classDocu.className.0 = 0 THEN
  823.   CALL LINEOUT docFile, CLASS_DOC_NONE
  824. ELSE
  825.   DO j = classDocu.className.0 TO 1 BY -1
  826.     CALL LINEOUT docFile,,
  827.                           changestr(classDocu.className.j,NLS_CHAR_ESC,NLS_CHAR)
  828.   END                              /* DO j = classDocu.className.0 TO 1 BY -1 */
  829. CALL LINEOUT docFile, '</P><HR>'
  830. RETURN
  831.  
  832. /* -------------------------------------------------------------------------- */
  833. /* printClassInterface: class interface                                       */
  834. /* -------------------------------------------------------------------------- */
  835. printClassInterface:
  836.  
  837. SAY MSG_CLASS_INTERFACE
  838.  
  839. CALL LINEOUT docFile, '<H2><A NAME="'CLASS_INT_H2'">'CLASS_INT_H2'</A></H2><P>'
  840. IF classInterf.className.0 = 0 THEN
  841.   CALL LINEOUT docFile, CLASS_INT_NONE
  842. ELSE DO
  843.   CALL LINEOUT docFile, '<PRE>'
  844.   doneInternalLinks = ''
  845.  
  846.   comment = 0
  847.   DO j=1 TO classInterf.className.0
  848.     line = classInterf.className.j
  849.  
  850.     /* skip comment lines   ----------------------------------------------- */
  851.  
  852.     IF LEFT(STRIP(line),2) = '//' THEN DO
  853.       line = changestr(line,'°amp; < >','& < >')
  854.       line = changestr(line,'&','°')
  855.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  856.       ITERATE
  857.     END                              /* IF LEFT(STRIP(line),2) = '//' THEN DO */
  858.     ELSE IF comment & POS('*/',line) = 0 THEN DO
  859.       line = changestr(line,'°amp; < >','& < >')
  860.       line = changestr(line,'&','°')
  861.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  862.       ITERATE
  863.     END
  864.     ELSE IF comment THEN DO
  865.       comment = 0
  866.       line = changestr(line,'°amp; < >','& < >')
  867.       line = changestr(line,'&','°')
  868.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  869.       ITERATE
  870.     END                                            /* ELSE IF comment THEN DO */
  871.     ELSE IF POS('/*',line) > 0 & POS('*/',line) = 0 THEN DO
  872.       comment = 1
  873.       line = changestr(line,'°amp; < >','& < >')
  874.       line = changestr(line,'&','°')
  875.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  876.       ITERATE
  877.     END            /* ELSE IF POS('/*',line) > 0 & POS('*/',line) = 0 THEN DO */
  878.     ELSE IF POS('/*',line) > 0 THEN DO
  879.       line = changestr(line,'°amp; < >','& < >')
  880.       line = changestr(line,'&','°')
  881.       CALL LINEOUT docFile, changestr(line,NLS_CHAR_ESC,NLS_CHAR)
  882.       ITERATE
  883.     END
  884.  
  885.     /* print keywords private:, protected: and public: in bold   ------------ */
  886.  
  887.     IF WORDPOS('private:',line) > 0 THEN DO
  888.       CALL LINEOUT docFile, '</PRE>'
  889.       CALL LINEOUT docFile, changestr(line,'<B>private:</B>','private:',,,1)
  890.       CALL LINEOUT docFile, '<PRE>'
  891.       ITERATE
  892.     END                            /* IF WORDPOS('private:',line) > 0 THEN DO */
  893.     IF WORDPOS('protected:',line) > 0 THEN DO
  894.       CALL LINEOUT docFile, '</PRE>'
  895.       CALL LINEOUT docFile,,
  896.                             changestr(line,'<B>protected:</B>','protected:',,,1)
  897.       CALL LINEOUT docFile, '<PRE>'
  898.       ITERATE
  899.     END                          /* IF WORDPOS('protected:',line) > 0 THEN DO */
  900.     IF WORDPOS('public:',line) > 0 THEN DO
  901.       CALL LINEOUT docFile, '</PRE>'
  902.       CALL LINEOUT docFile, changestr(line,'<B>public:</B>','public:',,,1)
  903.       CALL LINEOUT docFile, '<PRE>'
  904.       ITERATE
  905.     END                             /* IF WORDPOS('public:',line) > 0 THEN DO */
  906.  
  907.     /* check for internal links   ------------------------------------------- */
  908.  
  909.     IF POS('(',line) > 0 THEN DO
  910.       ident = lastIdentifier(line,POS('(',line))
  911.       line  = changestr(line,'°amp; < >','& < >')
  912.       line  = changestr(line,'&','°')
  913.       ident = changestr(ident,'°amp; < >','& < >')
  914.       ident = changestr(ident,'&','°')
  915.       IF WORDPOS(SPACE(ident,0),classMember.className) > 0 THEN
  916.         DO k = WORDPOS(SPACE(ident,0),classMember.className) TO,
  917.                                                     WORDS(classMember.className)
  918.           member = WORD(classMember.className,k)
  919.           IF ABBREV(member,SPACE(ident,0)) &,
  920.                                    WORDPOS(member,doneInternalLinks) = 0 THEN DO
  921.             line = makeInternalRef(line,ident,member)
  922.             doneInternalLinks = doneInternalLinks member
  923.             LEAVE
  924.           END                /* WORDPOS(member,doneInternalLinks) = 0 THEN DO */
  925.         END       /* DO k = WORDPOS(SPACE(ident,0),classMember.className) TO, */
  926.     END                                       /* IF POS('(',line) > 0 THEN DO */
  927.       ELSE DO
  928.         line = changestr(line,'°amp; < >','& < >')
  929.         line = changestr(line,'&','°')
  930.       END                                                          /* ELSE DO */
  931.  
  932.     line = makeExternalRef(changestr(line,NLS_CHAR_ESC,NLS_CHAR))
  933.     CALL LINEOUT docFile, line
  934.   END                                    /* DO j=1 TO classInterf.className.0 */
  935.   CALL LINEOUT docFile, '</PRE>'
  936. END                                                                /* ELSE DO */
  937. CALL LINEOUT docFile, '</P><HR>'
  938. RETURN
  939.  
  940. /* -------------------------------------------------------------------------- */
  941. /* printMemberDoc: member description                                         */
  942. /* -------------------------------------------------------------------------- */
  943. printMemberDoc:
  944.  
  945. SAY MSG_MEMBER_DOC
  946.  
  947. CALL LINEOUT docFile, '<H2>'MEMBER_DOC_H2'</H2><P>'
  948. IF WORDS(classMember.className) = 0 THEN
  949.   CALL LINEOUT docFile, MEMBER_DOC_NONE '</P><HR>'
  950. ELSE
  951.   DO j=1 TO WORDS(classMember.className)
  952.     memberName = WORD(classMember.className,j)
  953.     PARSE VALUE memberName WITH memberTitle_H3 '!' .
  954.     CALL LINEOUT docFile, '<H3><A NAME="'memberName'">'memberTitle_H3 ||,
  955.                                                                   '</A></H3><P>'
  956.  
  957.     /* member definition ---------------------------------------------------- */
  958.  
  959.     indent = 0
  960.     CALL LINEOUT docFile, '<PRE>'
  961.     def = memberDef.className.memberName
  962.     DO WHILE LENGTH(def) > MAX_LINE_LENGTH
  963.       splitPos = LASTPOS(',',def,MAX_LINE_LENGTH)
  964.       IF splitPos = 0 THEN
  965.         splitPos = LASTPOS(' ',def,MAX_LINE_LENGTH)
  966.       token = changestr(SUBSTR(def,1,splitPos),'°amp; < >','& < >')
  967.       token = changestr(token,'&','°')
  968.       def   = STRIP(SUBSTR(def,splitPos+1))
  969.       CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(token)
  970.       indent = 5
  971.     END                             /* DO WHILE LENGTH(def) > MAX_LINE_LENGTH */
  972.     def = changestr(def,'°amp; < >','& < >')
  973.     def = changestr(def,'&','°')
  974.     CALL LINEOUT docFile, COPIES(' ',indent) makeExternalRef(def)
  975.     CALL LINEOUT docFile, '</PRE></P><P>'
  976.  
  977.     /* member description   ------------------------------------------------- */
  978.  
  979.     DO k=1 TO memberDocu.className.memberName.0
  980.       CALL LINEOUT docFile,,
  981.             changestr(memberDocu.className.memberName.k,NLS_CHAR_ESC,NLS_CHAR)
  982.     END                        /* DO k=1 TO memberDocu.className.memberName.0 */
  983.     CALL LINEOUT docFile, '</P><P><A HREF="#'CLASS_INT_H2'">' ||,
  984.                                                      CLASS_INT_REF'</A></P><HR>'
  985.   END                               /* DO j=1 TO WORDS(classMember.className) */
  986. RETURN
  987.  
  988. /* -------------------------------------------------------------------------- */
  989. /* printTrailer: trailer for HTML-file                                        */
  990. /* -------------------------------------------------------------------------- */
  991. printTrailer:
  992.  
  993. ARG targetFile
  994.  
  995. IF omitTrailer THEN DO
  996.   CALL LINEOUT targetFile, '<P>CPPDOC - (C) by Bernhard Bablok, 1996</P>'
  997.   CALL LINEOUT targetFile, '<P>Please send comments, suggestions, bug-reports to:'
  998.   CALL LINEOUT targetFile, '<A HREF="mailto:ua302cb@sunmail.lrz-muenchen.de">' ||,
  999.                                                          'Bernhard Bablok</A></P>'
  1000. END
  1001. CALL LINEOUT targetFile, '</BODY>'
  1002. CALL LINEOUT targetFile, '</HTML>'
  1003. RETURN
  1004.  
  1005. /* -------------------------------------------------------------------------- */
  1006. /* updateIndexFile: add index entries                                         */
  1007. /* -------------------------------------------------------------------------- */
  1008. updateIndexFile:
  1009.  
  1010. IF indexFile = '' THEN
  1011.   RETURN
  1012.  
  1013. IF STREAM(indexFile,'C','query exists') = '' THEN DO
  1014.   CALL LINEOUT indexFile, '<!-- Class index generated by CPPDOC -->'
  1015.   CALL LINEOUT indexFile, '<HTML>'
  1016.   CALL LINEOUT indexFile, '<HEAD>'
  1017.   CALL LINEOUT indexFile, '<TITLE>'INDEX_TITLE'</TITLE>'
  1018.   CALL LINEOUT indexFile, '</HEAD>'
  1019.   CALL LINEOUT indexFile, '<BODY>'
  1020.   CALL LINEOUT indexFile, '<H1>'INDEX_H1'</H1><P><UL>'
  1021.   DO i=1 TO WORDS(externalRefsClassList)
  1022.     className = WORD(externalRefsClassList,i)
  1023.     CALL LINEOUT indexFile, '<LI><A HREF="'externalRefs.className ||,
  1024.                                                             '">'className'</A>',
  1025.                        changestr(classIndexInfo.className,NLS_CHAR_ESC,NLS_CHAR)
  1026.   END
  1027.   CALL LINEOUT indexFile, '</UL></P><HR>'
  1028.   CALL printTrailer indexFile
  1029.   CALL LINEOUT indexFile
  1030. END                   /* IF STREAM(indexFile,'C','query exists') = '' THEN DO */
  1031. ELSE DO
  1032.   CALL SysFileDelete indexFile
  1033.   DO i=1 TO indexAddBefore - 1
  1034.     IF WORDPOS(index.i._class,externalRefsClassList) = 0 THEN
  1035.       CALL LINEOUT indexFile, index.i
  1036.   END                                         /* DO i=1 TO indexAddBefore - 1 */
  1037.   DO i=1 TO WORDS(externalRefsClassList)
  1038.     className = WORD(externalRefsClassList,i)
  1039.     CALL LINEOUT indexFile, '<LI><A HREF="'externalRefs.className ||,
  1040.                                                             '">'className'</A>',
  1041.                        changestr(classIndexInfo.className,NLS_CHAR_ESC,NLS_CHAR)
  1042.   END
  1043.   DO i=indexAddBefore TO index.0
  1044.     IF WORDPOS(index.i._class,externalRefsClassList) = 0 THEN
  1045.       CALL LINEOUT indexFile, index.i
  1046.   END                                       /* DO i=indexAddBefore TO index.0 */
  1047.   CALL LINEOUT indexFile
  1048. END                                                                /* ELSE DO */
  1049. RETURN
  1050.  
  1051. /* -------------------------------------------------------------------------- */
  1052. /* usage: usage information                                                   */
  1053. /* -------------------------------------------------------------------------- */
  1054. usage:
  1055.  
  1056. SAY
  1057. SAY 'CPPDOC 1.10, (c) by Bernhard Bablok, 1996'
  1058. SAY
  1059. SAY 'Usage: cppdoc [-x indexFile] [-t targetDirectory] [-rH2sdim] file [file ...]'
  1060. SAY
  1061. SAY 'Options: -r use relative links'
  1062. SAY '         -H hide private sections (sections with tag //@p)'
  1063. SAY '         -2 process twice'
  1064. SAY '         -s print source reference   -|'
  1065. SAY '         -d print class description   |- default: print all'
  1066. SAY '         -i print class interface     |'
  1067. SAY '         -m print member description -|'
  1068. EXIT 1
  1069.  
  1070. /*-------------------------------------------------------------------------
  1071.     GetOpt - parse options from REXX program command line
  1072.  
  1073.     Copyright (c) 1994 Lawrence R Buchanan.  ALL RIGHTS RESERVED.
  1074.  -------------------------------------------------------------------------*/
  1075. GetOpt: PROCEDURE EXPOSE GetOpt.
  1076.     PARSE ARG optstr
  1077.  
  1078.     i = GetOpt._optind
  1079.     IF GetOpt._sp = 1 THEN DO
  1080.         IF GetOpt._optind > GetOpt.0 | ,
  1081.            SUBSTR(GetOpt.i, 1, 1, '00'x) <> '-' | ,
  1082.            SUBSTR(GetOpt.i, 2, 1, '00'x) = '00'x THEN
  1083.             RETURN -1
  1084.         ELSE
  1085.             IF GetOpt.i =  '--' THEN DO
  1086.                 GetOpt._optind = GetOpt._optind + 1
  1087.                 RETURN -1
  1088.             END
  1089.     END
  1090.  
  1091.     c = SUBSTR(GetOpt.i, GetOpt._sp+1, 1, '00'x)
  1092.     GetOpt._optopt = c
  1093.     cp = POS(c, optstr)
  1094.  
  1095.     IF c = ':' | cp = 0 THEN DO
  1096.         IF GetOpt._opterr = 1 THEN
  1097.             SAY GetOpt._program ': illegal option --' c
  1098.         GetOpt._sp = GetOpt._sp + 1
  1099.         IF SUBSTR(GetOpt.i, GetOpt._sp+1, 1, '00'x) = '00'x THEN DO
  1100.             GetOpt._optind = GetOpt._optind + 1
  1101.             GetOpt._sp = 1
  1102.         END
  1103.         RETURN '?'
  1104.     END
  1105.  
  1106.     cp = cp + 1
  1107.     IF SUBSTR(optstr, cp, 1, '00'x) = ':' THEN DO
  1108.         IF SUBSTR(GetOpt.i, GetOpt._sp+2, 1, '00'x) <> '00'x THEN DO
  1109.             GetOpt._optarg = SUBSTR(GetOpt.i, GetOpt._sp+2)
  1110.             GetOpt._optind = GetOpt._optind + 1
  1111.         END
  1112.         ELSE DO
  1113.             GetOpt._optind = GetOpt._optind + 1
  1114.             i = GetOpt._optind
  1115.             IF GetOpt._optind > GetOpt.0 THEN DO
  1116.                 IF GetOpt._opterr = 1 THEN
  1117.                     SAY GetOpt._program ': option requires an argument --' c
  1118.                 GetOpt._sp = 1
  1119.                 RETURN '?'
  1120.             END
  1121.             ELSE DO
  1122.                 GetOpt._optarg = GetOpt.i
  1123.                 GetOpt._optind = GetOpt._optind + 1
  1124.             END
  1125.         END
  1126.  
  1127.         GetOpt._sp = 1
  1128.     END
  1129.     ELSE DO
  1130.         GetOpt._sp = GetOpt._sp + 1
  1131.         IF SUBSTR(GetOpt.i, GetOpt._sp+1, 1, '00'x) = '00'x THEN DO
  1132.             GetOpt._sp = 1
  1133.             GetOpt._optind = GetOpt._optind + 1
  1134.         END
  1135.  
  1136.         GetOpt._optarg = ''
  1137.     END
  1138.  
  1139. RETURN c
  1140. /* End of GetOpt */
  1141.  
  1142.  
  1143. /*-------------------------------------------------------------------------
  1144.     SetupArg - Parse command-line arguments and store in stem GetOpt.
  1145.  
  1146.     Copyright (c) 1994 Lawrence R Buchanan.  ALL RIGHTS RESERVED.
  1147.  -------------------------------------------------------------------------*/
  1148. SetupArg: PROCEDURE EXPOSE GetOpt.
  1149.     PARSE ARG arglist
  1150.  
  1151.     /* Initialize variables used in GetOpt subroutine. */
  1152.     GetOpt. = ''
  1153.     GetOpt._opterr = 1
  1154.     GetOpt._optind = 1
  1155.     GetOpt._sp   = 1
  1156.  
  1157.     /* Place program name in GetOpt._program. */
  1158.     PARSE SOURCE os . GetOpt._program .
  1159.     IF os = 'OS/2' THEN DO
  1160.         GetOpt._program = FILESPEC('N', GetOpt._program)
  1161.         GetOpt._program = DELSTR(GetOpt._program, LASTPOS('.', GetOpt._program))
  1162.     END
  1163.  
  1164.     /* Make sure the command-line contains an even number of
  1165.         quotation characters.  If it doesn't, I can't continue. */
  1166.     IF count('"',arglist) // 2 THEN DO
  1167.         SAY GetOpt._program ': Unbalanced quotation marks in command-line'
  1168.         EXIT 255
  1169.     END
  1170.  
  1171.     i = 0
  1172.     /* Load command-line options into GetOpt.1 through GetOpt.n. */    
  1173.     DO WHILE arglist <> ''
  1174.         i = i + 1
  1175.         PARSE VAR arglist GetOpt.i arglist
  1176.  
  1177.         /* If quoted argument, make sure we get it all from command-line. */
  1178.         IF POS('"', GetOpt.i) > 0 THEN DO
  1179.             cnt = count('"',GetOpt.i)
  1180.             PARSE VAR GetOpt.i opt '"' tmparg
  1181.             GetOpt.i = opt || STRIP(tmparg, 'T', '"')
  1182.             IF cnt = 1 THEN DO
  1183.                 PARSE VAR arglist remarg '"' arglist
  1184.                 GetOpt.i = GetOpt.i remarg
  1185.             END
  1186.         END
  1187.     END
  1188.     GetOpt.0 = i
  1189.  
  1190. RETURN GetOpt.0
  1191. /* End of SetupArg */
  1192.